<template>
  <div class="home-container">
    <!-- 第一行：数据统计卡片 -->
    <el-row :gutter="20" class="data-row">
      <el-col :span="8">
        <el-card class="data-card" shadow="hover">
          <div class="data-content">
            <div class="data-info">
              <div class="data-title" style="margin-top: -18px;">活动签到人数</div>
              <div class="data-value">{{ statistics.signInCount }}</div>
              <div class="data-trend">
                较昨日 
                <span :class="statistics.signInTrend >= 0 ? 'up' : 'down'">
                  {{ Math.abs(statistics.signInTrend) }}%
                  <el-icon><CaretTop v-if="statistics.signInTrend >= 0" /><CaretBottom v-else /></el-icon>
                </span>
              </div>
            </div>
            <el-icon class="data-icon"><User /></el-icon>
          </div>
        </el-card>
      </el-col>
      <el-col :span="8">
        <el-card class="data-card" shadow="hover">
          <div class="data-content">
            <div class="data-info">
              <div class="data-title" style="margin-top: -18px;">会议在线人数</div>
              <div class="data-value">{{ statistics.onlineCount }}</div>
              <div class="data-trend">
                较昨日
                <span :class="statistics.onlineTrend >= 0 ? 'up' : 'down'">
                  {{ Math.abs(statistics.onlineTrend) }}%
                  <el-icon><CaretTop v-if="statistics.onlineTrend >= 0" /><CaretBottom v-else /></el-icon>
                </span>
              </div>
            </div>
            <el-icon class="data-icon"><VideoCamera /></el-icon>
          </div>
        </el-card>
      </el-col>
      <el-col :span="8">
        <el-card class="data-card" shadow="hover">
          <div class="data-content">
            <div class="data-info">
              <div class="data-title" style="margin-top: -18px;">资料下载次数</div>
              <div class="data-value">{{ statistics.downloadCount }}</div>
              <div class="data-trend">
                较昨日
                <span :class="statistics.downloadTrend >= 0 ? 'up' : 'down'">
                  {{ Math.abs(statistics.downloadTrend) }}%
                  <el-icon><CaretTop v-if="statistics.downloadTrend >= 0" /><CaretBottom v-else /></el-icon>
                </span>
              </div>
            </div>
            <el-icon class="data-icon"><Download /></el-icon>
          </div>
        </el-card>
      </el-col>
    </el-row>

    <!-- 第二行：最新信息列表 -->
    <el-row :gutter="20" class="info-row">
      <el-col :span="8">
        <el-card class="info-card" shadow="hover">
          <template #header>
            <div class="card-header">
              <span>最新会议</span>
              <el-button class="more-btn" text @click="router.push('/meetings')">
                更多<el-icon><ArrowRight /></el-icon>
              </el-button>
            </div>
          </template>
          <div class="link-list">
            <div v-for="meeting in latestMeetings" :key="meeting.id" class="link-item">
              <el-link :href="meeting.url" target="_blank" :underline="false">
                {{ meeting.name }}
                <span class="link-time">{{ meeting.time }}</span>
              </el-link>
            </div>
          </div>
        </el-card>
      </el-col>
      <el-col :span="8">
        <el-card class="info-card" shadow="hover">
          <template #header>
            <div class="card-header">
              <span>精彩活动</span>
              <el-button class="more-btn" text @click="router.push('/activities')">
                更多<el-icon><ArrowRight /></el-icon>
              </el-button>
            </div>
          </template>
          <div class="link-list">
            <div v-for="activity in latestActivities" :key="activity.id" class="link-item">
              <el-link :href="activity.url" target="_blank" :underline="false">
                {{ activity.name }}
                <span class="link-time">{{ activity.time }}</span>
              </el-link>
            </div>
          </div>
        </el-card>
      </el-col>
      <el-col :span="8">
        <el-card class="info-card" shadow="hover">
          <template #header>
            <div class="card-header">
              <span>最新资料</span>
              <el-button class="more-btn" text @click="router.push('/materials')">
                更多<el-icon><ArrowRight /></el-icon>
              </el-button>
            </div>
          </template>
          <div class="link-list">
            <div v-for="material in latestMaterials" :key="material.id" class="link-item">
              <el-link :href="material.url" target="_blank" :underline="false" @click="handleMaterialClick(material)">
                {{ material.name }}
                <span class="link-time">{{ material.time }}</span>
              </el-link>
            </div>
          </div>
        </el-card>
      </el-col>
    </el-row>

    <!-- 数据大屏 -->
    <el-row :gutter="20" class="dashboard-row">
      <el-col :span="12">
        <el-card class="dashboard-card">
          <div class="dashboard-title">会议参与人数趋势</div>
          <div ref="attendanceChart" class="chart"></div>
        </el-card>
      </el-col>
      <el-col :span="12">
        <el-card class="dashboard-card">
          <div class="dashboard-title">用户参会状态趋势</div>
          <div ref="userStatusChart" class="chart"></div>
        </el-card>
      </el-col>
      <el-col :span="12">
        <el-card class="dashboard-card">
          <div class="dashboard-title">资料下载量统计</div>
          <div ref="downloadChart" class="chart"></div>
        </el-card>
      </el-col>
      <el-col :span="12">
        <el-card class="dashboard-card">
          <div class="dashboard-title">关键词云图</div>
          <div ref="wordCloudChart" class="chart"></div>
        </el-card>
      </el-col>
    </el-row>

    <!-- 新增的图表行 -->
    <el-row :gutter="20" class="dashboard-row">
      <el-col :span="8">
        <el-card class="dashboard-card">
          <div class="dashboard-title">企业展示统计</div>
          <div ref="gridChart" class="chart"></div>
        </el-card>
      </el-col>
      <el-col :span="8">
        <el-card class="dashboard-card">
          <div class="dashboard-title">参会地区分布</div>
          <div ref="geoChart" class="chart"></div>
        </el-card>
      </el-col>
      <el-col :span="8">
        <el-card class="dashboard-card">
          <div class="dashboard-title">参会趋势分析</div>
          <div ref="timeChart" class="chart"></div>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import * as echarts from 'echarts'
import {
  User,
  VideoCamera,
  Download,
  ArrowRight,
  CaretTop,
  CaretBottom
} from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { 
  getAllParticipants, 
  getSignedParticipants, 
  getMeetCards, 
  getActivityCards, 
  getExhibitCards,
  getGridData,
  getGeoData,
  getTimeData,
  MeetCard,
  ActivityCard,
  ExhibitCard,
  GridItem,
  GeoData,
  TimeData
} from '@/api/home'

// 定义地图数据类型
interface ChinaMapFeature {
  type: "Feature";
  properties: {
    name: string;
  };
  geometry: {
    type: "Point";
    coordinates: [number, number];
  };
}

interface ChinaMap {
  type: "FeatureCollection";
  features: ChinaMapFeature[];
}


// 引入词云图模块
// import 'echarts/lib/chart/wordCloud'
import 'echarts-wordcloud';

const router = useRouter()

const attendanceChart = ref(null)
const userStatusChart = ref(null)
const downloadChart = ref(null)
const wordCloudChart = ref(null)
const gridChart = ref(null)
const geoChart = ref(null)
const timeChart = ref(null)

// 统计数据
const statistics = ref({
  signInCount: 89,
  signInTrend: 5.2,
  onlineCount: 148,
  onlineTrend: -2.1,
  downloadCount: 157,
  downloadTrend: 8.5
})

// 最新会议数据
const latestMeetings = ref<MeetCard[]>([])

// 最新活动数据
const latestActivities = ref<ActivityCard[]>([])

// 最新资料数据 - 使用自定义接口
interface MaterialDisplay {
  id: string | number
  name: string
  time: string
  url: string
}
const latestMaterials = ref<MaterialDisplay[]>([])

// 图表数据 - 使用模拟数据
const meetings = ref([
  { name: '西湖论剑·2024网络安全大会', registered: 328, attended: 312 },
  { name: '数字安全创新论坛', registered: 256, attended: 245 },
  { name: '零信任安全架构研讨会', registered: 189, attended: 178 },
  { name: '数据安全与隐私保护峰会', registered: 215, attended: 198 },
  { name: '云原生安全技术论坛', registered: 167, attended: 155 },
  { name: '工业互联网安全大会', registered: 198, attended: 182 }
])

const userStatusData = ref([
  { time: '2024-03-01', pending: 15, approved: 28, unsigned: 42, signed: 156 },
  { time: '2024-03-02', pending: 18, approved: 32, unsigned: 38, signed: 168 },
  { time: '2024-03-03', pending: 22, approved: 35, unsigned: 45, signed: 175 },
  { time: '2024-03-04', pending: 25, approved: 42, unsigned: 35, signed: 182 },
  { time: '2024-03-05', pending: 28, approved: 38, unsigned: 32, signed: 195 }
])

const downloadData = ref([
  { type: '安全白皮书', count: 156 },
  { type: '技术文档', count: 89 },
  { type: '会议资料', count: 234 },
  { type: '解决方案', count: 167 }
])

const keywords = ref([
  { name: '零信任', value: 100 },
  { name: '数据安全', value: 98 },
  { name: '云安全', value: 95 },
  { name: '隐私保护', value: 92 },
  { name: '工业互联网', value: 90 },
  { name: '安全架构', value: 88 },
  { name: '漏洞防护', value: 85 },
  { name: '安全运营', value: 82 },
  { name: '态势感知', value: 80 },
  { name: '安全合规', value: 78 },
  { name: '技术创新', value: 75 },
  { name: '数字赋能', value: 72 },
  { name: '智慧城市', value: 70 },
  { name: '网络安全', value: 68 },
  { name: '数字中国', value: 65 },
  { name: '产业升级', value: 62 },
  { name: '创新发展', value: 60 },
  { name: '科技强国', value: 58 },
  { name: '数字未来', value: 55 },
  { name: '安全生态', value: 52 },
  { name: '协同创新', value: 50 },
  { name: '数字治理', value: 48 },
  { name: '智慧生活', value: 45 },
  { name: '数字文明', value: 42 },
  { name: '安全守护', value: 40 }
])

// 在现有的ref声明后添加新的ref
const gridData = ref<GridItem[]>([])
const geoData = ref<GeoData>({})
const timeData = ref<TimeData>({})

// 获取参会人员总数
const fetchAllParticipants = async () => {
  try {
    const response = await getAllParticipants()
    // statistics.value.onlineCount = Number(response);
  } catch (error) {
    console.error('获取参会人员总数失败:', error)
  }
}

// 获取已签到人员总数
const fetchSignedParticipants = async () => {
  try {
    const response = await getSignedParticipants()
    // statistics.value.signInCount = Number(response);
  } catch (error) {
    console.error('获取已签到人员总数失败:', error)
  }
}

// 获取会议卡片列表
const fetchMeetCards = async () => {
  try {
    const response = await getMeetCards()
    // console.log("会议卡片列表", response);
    // 处理返回的数据，确保格式正确
    if (response && Array.isArray(response)) {
      // 转换日期格式并添加url字段
      latestMeetings.value = response.map(item => ({
        id: item.id,
        name: item.name,
        time: formatDate(item.time),
        url: `/meeting-detail/${item.id}` // 使用会议ID构建详情页URL
      }));
    } else {
      latestMeetings.value = [];
    }
    latestMeetings.value = latestMeetings.value.slice(0, 5);
    // console.log("会议卡片列表",latestMeetings.value);
  } catch (error) {
    console.error('获取会议卡片列表失败:', error)
    ElMessage.error('获取会议卡片列表失败')
  }
}

// 获取活动卡片列表
const fetchActivityCards = async () => {
  try {
    const response = await getActivityCards()
    // console.log("活动卡片列表", response);
    // 处理返回的数据，确保格式正确
    if (response && Array.isArray(response)) {
      // 转换日期格式
      latestActivities.value = response.map(item => ({
        id: item.id,
        name: item.name,
        time: formatDate(item.time),
        url: item.url
      }));
    } else {
      latestActivities.value = [];
    }
    latestActivities.value = latestActivities.value.slice(0, 5);
  } catch (error) {
    console.error('获取活动卡片列表失败:', error)
    ElMessage.error('获取活动卡片列表失败')
  }
}

// 获取展品卡片列表
const fetchExhibitCards = async () => {
  try {
    const response = await getExhibitCards()
    // console.log("展品卡片列表", response);
    // 处理返回的数据，确保格式正确
    if (response && Array.isArray(response)) {
      // 转换展品数据为UI显示格式
      latestMaterials.value = response.map(item => ({
        id: item.id,
        name: item.name,
        time: new Date().toISOString().split('T')[0], // 使用当前日期作为默认值
        url: item.imageUrl || item.videoUrl || '#' // 使用图片或视频URL，如果没有则使用#
      }));
    } else {
      latestMaterials.value = [];
    }
    latestMaterials.value = latestMaterials.value.slice(0, 5);
  } catch (error) {
    console.error('获取展品卡片列表失败:', error)
    ElMessage.error('获取展品卡片列表失败')
  }
}

// 格式化日期函数
const formatDate = (dateString: string) => {
  try {
    // 处理CST格式的日期
    if (dateString.includes('CST')) {
      const date = new Date(dateString);
      return date.toISOString().split('T')[0];
    }
    // 处理ISO格式的日期
    else if (dateString.includes('T')) {
      return dateString.split('T')[0];
    }
    // 其他格式直接返回
    return dateString;
  } catch (error) {
    console.error('日期格式化失败:', error);
    return dateString;
  }
}

// 在现有的fetch函数后添加新的fetch函数
const fetchGridData = async () => {
  try {
    const response = await getGridData()
    gridData.value = response
    console.log("企业展示数据", gridData.value)
    drawGridChart() // 数据更新后重新绘制图表
  } catch (error) {
    console.error('获取企业展示数据失败:', error)
    ElMessage.error('获取企业展示数据失败')
  }
}

const fetchGeoData = async () => {
  try {
    const response = await getGeoData()
    geoData.value = response
    console.log("参会地区分布数据", geoData.value)
    drawGeoChart() // 数据更新后重新绘制图表
  } catch (error) {
    console.error('获取地理位置数据失败:', error)
    ElMessage.error('获取地理位置数据失败')
  }
}

const fetchTimeData = async () => {
  try {
    const response = await getTimeData()
    timeData.value = response
    console.log("参会趋势分析数据", timeData.value)
    drawTimeChart() // 数据更新后重新绘制图表
  } catch (error) {
    console.error('获取时间趋势数据失败:', error)
    ElMessage.error('获取时间趋势数据失败')
  }
}

// 初始化数据
const initData = async () => {
  await Promise.all([
    fetchAllParticipants(),
    fetchSignedParticipants(),
    fetchMeetCards(),
    fetchActivityCards(),
    fetchExhibitCards(),
    fetchGridData(),
    fetchGeoData(),
    fetchTimeData()
  ])
}

const drawAttendanceChart = () => {
  if (!attendanceChart.value) {
    console.error('Attendance Chart DOM not found!')
    return
  }
  const myChart = echarts.init(attendanceChart.value)

  const option = {
    title: {
      text: '会议参与人数趋势',
      subtext: '报名人数 vs 实际参会人数',
      left: 'center'
    },
    tooltip: {
      trigger: 'axis'
    },
    legend: {
      data: ['报名人数', '实际参会人数', '签到率'],
      bottom: '10%'
    },
    grid: {
      top: '15%',
      bottom: '15%',
      left: '3%',
      right: '4%',
      containLabel: true
    },
    xAxis: {
      type: 'category',
      data: meetings.value.map(meeting => meeting.name)
    },
    yAxis: [
      {
        type: 'value',
        name: '人数'
      },
      {
        type: 'value',
        name: '签到率',
        position: 'right'
      }
    ],
    series: [
      {
        name: '报名人数',
        type: 'bar',
        data: meetings.value.map(meeting => meeting.registered),
        emphasis: {
          focus: 'series'
        }
      },
      {
        name: '实际参会人数',
        type: 'bar',
        data: meetings.value.map(meeting => meeting.attended),
        emphasis: {
          focus: 'series'
        }
      },
      {
        name: '签到率',
        type: 'line',
        data: meetings.value.map(meeting => (meeting.attended / meeting.registered) * 100),
        yAxisIndex: 1
      }
    ]
  }

  myChart.setOption(option)
}

const drawUserStatusChart = () => {
  if (!userStatusChart.value) {
    console.error('User Status Chart DOM not found!')
    return
  }
  const myChart = echarts.init(userStatusChart.value)

  const option = {
    title: {
      text: '用户参会状态趋势',
      left: 'center'
    },
    tooltip: {
      trigger: 'axis'
    },
    legend: {
      data: ['未允许参会', '已允许参会', '未签到', '已签到'],
      bottom: '10%'
    },
    grid: {
      top: '15%',
      bottom: '15%',
      left: '3%',
      right: '4%',
      containLabel: true
    },
    xAxis: {
      type: 'category',
      data: userStatusData.value.map(data => data.time)
    },
    yAxis: {
      type: 'value',
      name: '用户数量'
    },
    series: [
      {
        name: '未允许参会',
        type: 'line',
        data: userStatusData.value.map(data => data.pending)
      },
      {
        name: '已允许参会',
        type: 'line',
        data: userStatusData.value.map(data => data.approved)
      },
      {
        name: '未签到',
        type: 'line',
        data: userStatusData.value.map(data => data.unsigned)
      },
      {
        name: '已签到',
        type: 'line',
        data: userStatusData.value.map(data => data.signed)
      }
    ]
  }

  myChart.setOption(option)
}

const drawDownloadChart = () => {
  if (!downloadChart.value) {
    console.error('Download Chart DOM not found!')
    return
  }
  const myChart = echarts.init(downloadChart.value)

  const option = {
    title: {
      text: '资料下载量统计',
      left: 'center'
    },
    tooltip: {
      trigger: 'item'
    },
    legend: {
      orient: 'vertical',
      left: 'left'
    },
    xAxis: {
      type: 'category',
      data: downloadData.value.map(data => data.type)
    },
    yAxis: {
      type: 'value',
      name: '下载次数'
    },
    series: [
      {
        name: '下载次数',
        type: 'bar',
        data: downloadData.value.map(data => data.count),
        emphasis: {
          focus: 'series'
        }
      }
    ]
  }

  myChart.setOption(option)
}

const drawWordCloudChart = () => {
  console.log('Word Cloud Chart init!')
  if (!wordCloudChart.value) {
    console.error('Word Cloud Chart DOM not found!')
    return
  }
  const myChart = echarts.init(wordCloudChart.value)

  const option = {
    title: {
      text: '关键词云图',
      left: 'center'
    },
    series: [{
      type: 'wordCloud',
      gridSize: 20,
      sizeRange: [10, 100],
      textStyle: {
        normal: {
          color: '#fff'
        },
        emphasis: {
          shadowBlur: 10,
          shadowColor: '#333'
        }
      },
      data: keywords.value.map(keyword => ({
        name: keyword.name,
        value: keyword.value,
      }))
    }]
  }

  myChart.setOption(option)
}

// 处理资料点击
const handleMaterialClick = (material: MaterialDisplay) => {
  // 如果是图片或视频URL，直接打开
  if (material.url.startsWith('http')) {
    window.open(material.url, '_blank');
  } else {
    // 否则导航到详情页
    router.push(`/material-detail/${material.id}`);
  }
}

// 在现有的draw函数后添加新的draw函数
const drawGridChart = () => {
  if (!gridChart.value) {
    console.error('Grid Chart DOM not found!')
    return
  }
  const myChart = echarts.init(gridChart.value)

  const option = {
    title: {
      text: '会议类别分布',
      left: 'center'
    },
    tooltip: {
      trigger: 'item',
      formatter: '{b}: {c} ({d}%)'
    },
    legend: {
      orient: 'vertical',
      left: 'left'
    },
    series: [
      {
        name: '会议类别',
        type: 'pie',
        radius: '50%',
        data: Object.entries(gridData.value).map(([name, value]) => ({
          name: name,
          value: value
        })),
        emphasis: {
          itemStyle: {
            shadowBlur: 10,
            shadowOffsetX: 0,
            shadowColor: 'rgba(0, 0, 0, 0.5)'
          }
        }
      }
    ]
  }

  myChart.setOption(option)
}

const drawGeoChart = () => {
  if (!geoChart.value) {
    console.error('Geo Chart DOM not found!')
    return
  }
  const myChart = echarts.init(geoChart.value)

  const option = {
    title: {
      text: '参会地区分布',
      left: 'center'
    },
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'shadow'
      }
    },
    xAxis: {
      type: 'category',
      data: Object.keys(geoData.value),
      axisLabel: {
        interval: 0,
        rotate: 30
      }
    },
    yAxis: {
      type: 'value',
      name: '参会人数'
    },
    series: [
      {
        name: '参会人数',
        type: 'bar',
        data: Object.entries(geoData.value).map(([name, value]) => ({
          name: name,
          value: value
        })),
        itemStyle: {
          color: '#409EFF'
        }
      }
    ]
  }

  myChart.setOption(option)
}

const drawTimeChart = () => {
  if (!timeChart.value) {
    console.error('Time Chart DOM not found!')
    return
  }
  const myChart = echarts.init(timeChart.value)

  // 将月份数据转换为数组并排序
  const months = Object.keys(timeData.value).sort()
  const allData = months.map(month => timeData.value[month].all)
  const signedData = months.map(month => timeData.value[month].signed)

  const option = {
    title: {
      text: '参会趋势分析',
      left: 'center'
    },
    tooltip: {
      trigger: 'axis',
      formatter: function(params: any[]) {
        const month = params[0].axisValue
        return `${month}<br/>
                总参会人数: ${params[0].value}<br/>
                已签到人数: ${params[1].value}`
      }
    },
    legend: {
      data: ['总参会人数', '已签到人数'],
      bottom: 0
    },
    grid: {
      left: '3%',
      right: '4%',
      bottom: '15%',
      top: '15%',
      containLabel: true
    },
    xAxis: {
      type: 'category',
      data: months.map(month => `${month}月`),
      axisLabel: {
        interval: 'auto',
        rotate: 45,
        fontSize: 12,
        margin: 15
      },
      boundaryGap: true
    },
    yAxis: {
      type: 'value',
      name: '人数',
      minInterval: 1,
      splitLine: {
        show: true,
        lineStyle: {
          type: 'dashed'
        }
      }
    },
    series: [
      {
        name: '总参会人数',
        type: 'line',
        data: allData,
        smooth: true,
        symbol: 'circle',
        symbolSize: 8,
        itemStyle: {
          color: '#409EFF'
        },
        lineStyle: {
          width: 2
        }
      },
      {
        name: '已签到人数',
        type: 'line',
        data: signedData,
        smooth: true,
        symbol: 'circle',
        symbolSize: 8,
        itemStyle: {
          color: '#67C23A'
        },
        lineStyle: {
          width: 2
        }
      }
    ]
  }

  myChart.setOption(option)
}

onMounted(() => {
  initData()
  drawAttendanceChart()
  drawUserStatusChart()
  drawDownloadChart()
  drawWordCloudChart()
})
</script>

<style scoped>
.home-container {
  padding: 20px;
}

.data-row {
  margin-bottom: 20px;
}

.data-card {
  height: 160px;
  transition: all 0.3s;
}

.data-card:hover {
  transform: translateY(-5px);
}

.data-content {
  height: 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px;
}

.data-info {
  flex: 1;
  /* padding-bottom: 50px; */
}

.data-title {
  font-size: 16px;
  color: #666;
  margin-bottom: 15px;
  /* padding-bottom: 50px; */
}

.data-value {
  font-size: 36px;
  font-weight: bold;
  color: #303133;
  margin-bottom: 10px;
}

.data-trend {
  font-size: 14px;
  color: #909399;
}

.data-trend .up {
  color: #67c23a;
}

.data-trend .down {
  color: #f56c6c;
}

.data-icon {
  font-size: 48px;
  color: #409eff;
  opacity: 0.8;
}

.info-row {
  margin-bottom: 20px;
}

.info-card {
  min-height: 300px;
  transition: all 0.3s;
}

.info-card:hover {
  transform: translateY(-5px);
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 16px;
  font-weight: bold;
}

.more-btn {
  font-size: 14px;
  color: #909399;
}

.link-list {
  .link-item {
    padding: 12px 0;
    border-bottom: 1px solid #ebeef5;
    
    &:last-child {
      border-bottom: none;
    }

    .el-link {
      display: flex;
      justify-content: space-between;
      align-items: center;
      width: 100%;
      font-size: 14px;
      
      &:hover {
        color: #409eff;
      }
    }

    .link-time {
      font-size: 12px;
      color: #909399;
    }
  }
}

.dashboard-row {
  margin-bottom: 20px;
}

.dashboard-card {
  height: 600px;
  text-align: center;
}

.dashboard-title {
  font-size: 24px;
  color: #2c3e50;
  padding: 20px;
}

.chart {
  width: 100%;
  height: 520px;
}
</style> 